alita-sdk 0.3.257__py3-none-any.whl → 0.3.584__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of alita-sdk might be problematic. Click here for more details.
- alita_sdk/cli/__init__.py +10 -0
- alita_sdk/cli/__main__.py +17 -0
- alita_sdk/cli/agent/__init__.py +5 -0
- alita_sdk/cli/agent/default.py +258 -0
- alita_sdk/cli/agent_executor.py +155 -0
- alita_sdk/cli/agent_loader.py +215 -0
- alita_sdk/cli/agent_ui.py +228 -0
- alita_sdk/cli/agents.py +3794 -0
- alita_sdk/cli/callbacks.py +647 -0
- alita_sdk/cli/cli.py +168 -0
- alita_sdk/cli/config.py +306 -0
- alita_sdk/cli/context/__init__.py +30 -0
- alita_sdk/cli/context/cleanup.py +198 -0
- alita_sdk/cli/context/manager.py +731 -0
- alita_sdk/cli/context/message.py +285 -0
- alita_sdk/cli/context/strategies.py +289 -0
- alita_sdk/cli/context/token_estimation.py +127 -0
- alita_sdk/cli/formatting.py +182 -0
- alita_sdk/cli/input_handler.py +419 -0
- alita_sdk/cli/inventory.py +1073 -0
- alita_sdk/cli/mcp_loader.py +315 -0
- alita_sdk/cli/toolkit.py +327 -0
- alita_sdk/cli/toolkit_loader.py +85 -0
- alita_sdk/cli/tools/__init__.py +43 -0
- alita_sdk/cli/tools/approval.py +224 -0
- alita_sdk/cli/tools/filesystem.py +1751 -0
- alita_sdk/cli/tools/planning.py +389 -0
- alita_sdk/cli/tools/terminal.py +414 -0
- alita_sdk/community/__init__.py +72 -12
- alita_sdk/community/inventory/__init__.py +236 -0
- alita_sdk/community/inventory/config.py +257 -0
- alita_sdk/community/inventory/enrichment.py +2137 -0
- alita_sdk/community/inventory/extractors.py +1469 -0
- alita_sdk/community/inventory/ingestion.py +3172 -0
- alita_sdk/community/inventory/knowledge_graph.py +1457 -0
- alita_sdk/community/inventory/parsers/__init__.py +218 -0
- alita_sdk/community/inventory/parsers/base.py +295 -0
- alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
- alita_sdk/community/inventory/parsers/go_parser.py +851 -0
- alita_sdk/community/inventory/parsers/html_parser.py +389 -0
- alita_sdk/community/inventory/parsers/java_parser.py +593 -0
- alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
- alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
- alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
- alita_sdk/community/inventory/parsers/python_parser.py +604 -0
- alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
- alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
- alita_sdk/community/inventory/parsers/text_parser.py +322 -0
- alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
- alita_sdk/community/inventory/patterns/__init__.py +61 -0
- alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
- alita_sdk/community/inventory/patterns/loader.py +348 -0
- alita_sdk/community/inventory/patterns/registry.py +198 -0
- alita_sdk/community/inventory/presets.py +535 -0
- alita_sdk/community/inventory/retrieval.py +1403 -0
- alita_sdk/community/inventory/toolkit.py +173 -0
- alita_sdk/community/inventory/toolkit_utils.py +176 -0
- alita_sdk/community/inventory/visualize.py +1370 -0
- alita_sdk/configurations/__init__.py +11 -0
- alita_sdk/configurations/ado.py +148 -2
- alita_sdk/configurations/azure_search.py +1 -1
- alita_sdk/configurations/bigquery.py +1 -1
- alita_sdk/configurations/bitbucket.py +94 -2
- alita_sdk/configurations/browser.py +18 -0
- alita_sdk/configurations/carrier.py +19 -0
- alita_sdk/configurations/confluence.py +130 -1
- alita_sdk/configurations/delta_lake.py +1 -1
- alita_sdk/configurations/figma.py +76 -5
- alita_sdk/configurations/github.py +65 -1
- alita_sdk/configurations/gitlab.py +81 -0
- alita_sdk/configurations/google_places.py +17 -0
- alita_sdk/configurations/jira.py +103 -0
- alita_sdk/configurations/openapi.py +323 -0
- alita_sdk/configurations/postman.py +1 -1
- alita_sdk/configurations/qtest.py +72 -3
- alita_sdk/configurations/report_portal.py +115 -0
- alita_sdk/configurations/salesforce.py +19 -0
- alita_sdk/configurations/service_now.py +1 -12
- alita_sdk/configurations/sharepoint.py +167 -0
- alita_sdk/configurations/sonar.py +18 -0
- alita_sdk/configurations/sql.py +20 -0
- alita_sdk/configurations/testio.py +101 -0
- alita_sdk/configurations/testrail.py +88 -0
- alita_sdk/configurations/xray.py +94 -1
- alita_sdk/configurations/zephyr_enterprise.py +94 -1
- alita_sdk/configurations/zephyr_essential.py +95 -0
- alita_sdk/runtime/clients/artifact.py +21 -4
- alita_sdk/runtime/clients/client.py +458 -67
- alita_sdk/runtime/clients/mcp_discovery.py +342 -0
- alita_sdk/runtime/clients/mcp_manager.py +262 -0
- alita_sdk/runtime/clients/sandbox_client.py +352 -0
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +183 -43
- alita_sdk/runtime/langchain/constants.py +647 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +209 -31
- alita_sdk/runtime/langchain/document_loaders/AlitaImageLoader.py +1 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaMarkdownLoader.py +66 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaPDFLoader.py +79 -10
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +52 -15
- alita_sdk/runtime/langchain/document_loaders/AlitaPythonLoader.py +9 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaTableLoader.py +1 -4
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +15 -2
- alita_sdk/runtime/langchain/document_loaders/ImageParser.py +30 -0
- alita_sdk/runtime/langchain/document_loaders/constants.py +189 -41
- alita_sdk/runtime/langchain/interfaces/llm_processor.py +4 -2
- alita_sdk/runtime/langchain/langraph_agent.py +493 -105
- alita_sdk/runtime/langchain/utils.py +118 -8
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/models/mcp_models.py +61 -0
- alita_sdk/runtime/skills/__init__.py +91 -0
- alita_sdk/runtime/skills/callbacks.py +498 -0
- alita_sdk/runtime/skills/discovery.py +540 -0
- alita_sdk/runtime/skills/executor.py +610 -0
- alita_sdk/runtime/skills/input_builder.py +371 -0
- alita_sdk/runtime/skills/models.py +330 -0
- alita_sdk/runtime/skills/registry.py +355 -0
- alita_sdk/runtime/skills/skill_runner.py +330 -0
- alita_sdk/runtime/toolkits/__init__.py +28 -0
- alita_sdk/runtime/toolkits/application.py +14 -4
- alita_sdk/runtime/toolkits/artifact.py +25 -9
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +782 -0
- alita_sdk/runtime/toolkits/planning.py +178 -0
- alita_sdk/runtime/toolkits/skill_router.py +238 -0
- alita_sdk/runtime/toolkits/subgraph.py +11 -6
- alita_sdk/runtime/toolkits/tools.py +314 -70
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +24 -0
- alita_sdk/runtime/tools/application.py +16 -4
- alita_sdk/runtime/tools/artifact.py +367 -33
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +100 -4
- alita_sdk/runtime/tools/graph.py +81 -0
- alita_sdk/runtime/tools/image_generation.py +218 -0
- alita_sdk/runtime/tools/llm.py +1032 -177
- alita_sdk/runtime/tools/loop.py +3 -1
- alita_sdk/runtime/tools/loop_output.py +3 -1
- alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
- alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
- alita_sdk/runtime/tools/mcp_server_tool.py +3 -1
- alita_sdk/runtime/tools/planning/__init__.py +36 -0
- alita_sdk/runtime/tools/planning/models.py +246 -0
- alita_sdk/runtime/tools/planning/wrapper.py +607 -0
- alita_sdk/runtime/tools/router.py +2 -1
- alita_sdk/runtime/tools/sandbox.py +375 -0
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +69 -65
- alita_sdk/runtime/tools/vectorstore_base.py +163 -90
- alita_sdk/runtime/utils/AlitaCallback.py +137 -21
- alita_sdk/runtime/utils/constants.py +5 -1
- alita_sdk/runtime/utils/mcp_client.py +492 -0
- alita_sdk/runtime/utils/mcp_oauth.py +361 -0
- alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/streamlit.py +41 -14
- alita_sdk/runtime/utils/toolkit_utils.py +28 -9
- alita_sdk/runtime/utils/utils.py +48 -0
- alita_sdk/tools/__init__.py +135 -37
- alita_sdk/tools/ado/__init__.py +2 -2
- alita_sdk/tools/ado/repos/__init__.py +16 -19
- alita_sdk/tools/ado/repos/repos_wrapper.py +12 -20
- alita_sdk/tools/ado/test_plan/__init__.py +27 -8
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +56 -28
- alita_sdk/tools/ado/wiki/__init__.py +28 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +114 -40
- alita_sdk/tools/ado/work_item/__init__.py +28 -12
- alita_sdk/tools/ado/work_item/ado_wrapper.py +95 -11
- alita_sdk/tools/advanced_jira_mining/__init__.py +13 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +15 -11
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +14 -8
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +454 -110
- alita_sdk/tools/bitbucket/__init__.py +28 -19
- alita_sdk/tools/bitbucket/api_wrapper.py +285 -27
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +5 -5
- alita_sdk/tools/browser/__init__.py +41 -16
- alita_sdk/tools/browser/crawler.py +3 -1
- alita_sdk/tools/browser/utils.py +15 -6
- alita_sdk/tools/carrier/__init__.py +18 -17
- alita_sdk/tools/carrier/backend_reports_tool.py +8 -4
- alita_sdk/tools/carrier/excel_reporter.py +8 -4
- alita_sdk/tools/chunkers/__init__.py +3 -1
- alita_sdk/tools/chunkers/code/codeparser.py +1 -1
- alita_sdk/tools/chunkers/sematic/json_chunker.py +2 -1
- alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
- alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
- alita_sdk/tools/chunkers/universal_chunker.py +270 -0
- alita_sdk/tools/cloud/aws/__init__.py +12 -7
- alita_sdk/tools/cloud/azure/__init__.py +12 -7
- alita_sdk/tools/cloud/gcp/__init__.py +12 -7
- alita_sdk/tools/cloud/k8s/__init__.py +12 -7
- alita_sdk/tools/code/linter/__init__.py +10 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +21 -13
- alita_sdk/tools/code_indexer_toolkit.py +199 -0
- alita_sdk/tools/confluence/__init__.py +22 -14
- alita_sdk/tools/confluence/api_wrapper.py +197 -58
- alita_sdk/tools/confluence/loader.py +14 -2
- alita_sdk/tools/custom_open_api/__init__.py +12 -5
- alita_sdk/tools/elastic/__init__.py +11 -8
- alita_sdk/tools/elitea_base.py +546 -64
- alita_sdk/tools/figma/__init__.py +60 -11
- alita_sdk/tools/figma/api_wrapper.py +1400 -167
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +18 -17
- alita_sdk/tools/github/api_wrapper.py +9 -26
- alita_sdk/tools/github/github_client.py +81 -12
- alita_sdk/tools/github/schemas.py +2 -1
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/gitlab/__init__.py +19 -13
- alita_sdk/tools/gitlab/api_wrapper.py +256 -80
- alita_sdk/tools/gitlab_org/__init__.py +14 -10
- alita_sdk/tools/google/bigquery/__init__.py +14 -13
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +21 -11
- alita_sdk/tools/jira/__init__.py +22 -11
- alita_sdk/tools/jira/api_wrapper.py +315 -168
- alita_sdk/tools/keycloak/__init__.py +11 -8
- alita_sdk/tools/localgit/__init__.py +9 -3
- alita_sdk/tools/localgit/local_git.py +62 -54
- alita_sdk/tools/localgit/tool.py +5 -1
- alita_sdk/tools/memory/__init__.py +38 -14
- alita_sdk/tools/non_code_indexer_toolkit.py +7 -2
- alita_sdk/tools/ocr/__init__.py +11 -8
- alita_sdk/tools/openapi/__init__.py +491 -106
- alita_sdk/tools/openapi/api_wrapper.py +1357 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +20 -12
- alita_sdk/tools/pandas/api_wrapper.py +40 -45
- alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
- alita_sdk/tools/postman/__init__.py +11 -11
- alita_sdk/tools/postman/api_wrapper.py +19 -8
- alita_sdk/tools/postman/postman_analysis.py +8 -1
- alita_sdk/tools/pptx/__init__.py +11 -10
- alita_sdk/tools/qtest/__init__.py +22 -14
- alita_sdk/tools/qtest/api_wrapper.py +1784 -88
- alita_sdk/tools/rally/__init__.py +13 -10
- alita_sdk/tools/report_portal/__init__.py +23 -16
- alita_sdk/tools/salesforce/__init__.py +22 -16
- alita_sdk/tools/servicenow/__init__.py +21 -16
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +17 -14
- alita_sdk/tools/sharepoint/api_wrapper.py +179 -39
- alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
- alita_sdk/tools/sharepoint/utils.py +8 -2
- alita_sdk/tools/slack/__init__.py +13 -8
- alita_sdk/tools/sql/__init__.py +22 -19
- alita_sdk/tools/sql/api_wrapper.py +71 -23
- alita_sdk/tools/testio/__init__.py +21 -13
- alita_sdk/tools/testrail/__init__.py +13 -11
- alita_sdk/tools/testrail/api_wrapper.py +214 -46
- alita_sdk/tools/utils/__init__.py +28 -4
- alita_sdk/tools/utils/content_parser.py +241 -55
- alita_sdk/tools/utils/text_operations.py +254 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +83 -27
- alita_sdk/tools/xray/__init__.py +18 -14
- alita_sdk/tools/xray/api_wrapper.py +58 -113
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +12 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +16 -9
- alita_sdk/tools/zephyr_enterprise/api_wrapper.py +30 -15
- alita_sdk/tools/zephyr_essential/__init__.py +16 -10
- alita_sdk/tools/zephyr_essential/api_wrapper.py +297 -54
- alita_sdk/tools/zephyr_essential/client.py +6 -4
- alita_sdk/tools/zephyr_scale/__init__.py +13 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +39 -31
- alita_sdk/tools/zephyr_squad/__init__.py +12 -7
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/METADATA +184 -37
- alita_sdk-0.3.584.dist-info/RECORD +452 -0
- alita_sdk-0.3.584.dist-info/entry_points.txt +2 -0
- alita_sdk/tools/bitbucket/tools.py +0 -304
- alita_sdk-0.3.257.dist-info/RECORD +0 -343
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.257.dist-info → alita_sdk-0.3.584.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Alita SDK CLI - Command-line interface for testing agents and toolkits.
|
|
3
|
+
|
|
4
|
+
This module provides a CLI alternative to the Streamlit interface, enabling
|
|
5
|
+
direct terminal access for GitHub Copilot integration and automation workflows.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .cli import cli
|
|
9
|
+
|
|
10
|
+
__all__ = ['cli']
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Entry point for running the Alita CLI as a module.
|
|
3
|
+
|
|
4
|
+
Usage:
|
|
5
|
+
python -m alita_sdk.cli [command] [options]
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
# Suppress warnings before any imports
|
|
9
|
+
import warnings
|
|
10
|
+
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
|
11
|
+
warnings.filterwarnings('ignore', category=UserWarning)
|
|
12
|
+
warnings.filterwarnings('ignore', message='Unverified HTTPS request')
|
|
13
|
+
|
|
14
|
+
from .cli import cli
|
|
15
|
+
|
|
16
|
+
if __name__ == '__main__':
|
|
17
|
+
cli()
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
DEFAULT_PROMPT = """You are **Alita**, a Testing Agent running in a terminal-based CLI assistant. Alita is an open-source, agentic testing interface. You are expected to be precise, safe, technical, and helpful.
|
|
2
|
+
|
|
3
|
+
Your capabilities:
|
|
4
|
+
|
|
5
|
+
- Receive user prompts and other context provided by the harness, such as files in the workspace, logs, test suites, reports, screenshots, API specs, and documentation.
|
|
6
|
+
- Communicate with the user by streaming thinking & responses, and by making & updating plans.
|
|
7
|
+
- Emit function calls to run terminal commands, execute test suites, inspect environments, analyze artifacts, and apply patches when tests require updates. Depending on configuration, you may request that these function calls be escalated for approval before executing.
|
|
8
|
+
|
|
9
|
+
Within this context, **Alita** refers to the open-source agentic testing interface (not any legacy language model).
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# How you work
|
|
14
|
+
|
|
15
|
+
## Personality
|
|
16
|
+
|
|
17
|
+
You are concise, direct, and friendly. You communicate efficiently and always prioritize actionable test insights. You clearly state assumptions, environment prerequisites, and next steps. Unless explicitly asked, you avoid excessively verbose explanations.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# AGENTS.md spec
|
|
22
|
+
|
|
23
|
+
`AGENTS.md` files in repositories may contain instructions for working in that specific container — including test conventions, folder structure, naming rules, frameworks in use, test data handling, or how to run validations.
|
|
24
|
+
|
|
25
|
+
Rules:
|
|
26
|
+
|
|
27
|
+
- The scope of an `AGENTS.md` file covers its entire directory subtree.
|
|
28
|
+
- Any file you touch must follow instructions from applicable `AGENTS.md` files.
|
|
29
|
+
- For conflicting instructions, deeper directory `AGENTS.md` takes precedence.
|
|
30
|
+
- Direct system/developer/user instructions always take precedence.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Responsiveness
|
|
35
|
+
|
|
36
|
+
### Preamble messages
|
|
37
|
+
|
|
38
|
+
Before running tool calls (executing tests, launching commands, applying patches), send a brief preface describing what you’re about to do. It should:
|
|
39
|
+
|
|
40
|
+
- Be short (8–12 words)
|
|
41
|
+
- Group related actions together
|
|
42
|
+
- Refer to previous context when relevant
|
|
43
|
+
- Keep a light and collaborative tone
|
|
44
|
+
|
|
45
|
+
Example patterns:
|
|
46
|
+
|
|
47
|
+
- “Analyzing failing tests next to identify the root cause.”
|
|
48
|
+
- “Running backend API tests now to reproduce the reported issue.”
|
|
49
|
+
- “About to patch selectors and re-run UI regression tests.”
|
|
50
|
+
- “Finished scanning logs; now checking flaky test patterns.”
|
|
51
|
+
- “Next I’ll generate missing test data and rerun.”
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Planning
|
|
56
|
+
|
|
57
|
+
Use `update_plan` when:
|
|
58
|
+
|
|
59
|
+
- Tasks involve multiple phases of testing
|
|
60
|
+
- The sequence of activities matters
|
|
61
|
+
- Ambiguity requires breaking down the approach
|
|
62
|
+
- The user requests step-wise execution
|
|
63
|
+
|
|
64
|
+
### Resuming existing plans
|
|
65
|
+
|
|
66
|
+
**Important**: Before creating a new plan, check if there's already an existing plan in progress:
|
|
67
|
+
|
|
68
|
+
- If the user says "continue" or similar, look at the current plan state shown in tool results
|
|
69
|
+
- If steps are already marked as completed (☑), **do not create a new plan** — continue executing the remaining uncompleted steps
|
|
70
|
+
- Only use `update_plan` to create a **new** plan when starting a fresh task
|
|
71
|
+
- Use `complete_step` to mark steps done as you finish them
|
|
72
|
+
|
|
73
|
+
When resuming after interruption (e.g., tool limit reached):
|
|
74
|
+
|
|
75
|
+
1. Review which steps are already completed (☑)
|
|
76
|
+
2. Identify the next uncompleted step (☐)
|
|
77
|
+
3. Continue execution from that step — do NOT recreate the plan
|
|
78
|
+
4. Mark steps complete as you go
|
|
79
|
+
|
|
80
|
+
Example of a **high-quality test-oriented plan**:
|
|
81
|
+
|
|
82
|
+
1. Reproduce failure locally
|
|
83
|
+
2. Capture failing logs + stack traces
|
|
84
|
+
3. Identify root cause in test or code
|
|
85
|
+
4. Patch locator + stabilize assertions
|
|
86
|
+
5. Run whole suite to confirm no regressions
|
|
87
|
+
|
|
88
|
+
Low-quality plans ("run tests → fix things → done") are not acceptable.
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Task execution
|
|
93
|
+
|
|
94
|
+
You are a **testing agent**, not just a code-writing agent. Your responsibilities include:
|
|
95
|
+
|
|
96
|
+
- Executing tests across frameworks (API, UI, mobile, backend, contract, load, security)
|
|
97
|
+
- Analyzing logs, failures, screenshots, metrics, stack traces
|
|
98
|
+
- Investigating flakiness, nondeterminism, environmental issues
|
|
99
|
+
- Generating missing tests or aligning test coverage to requirements
|
|
100
|
+
- Proposing (and applying when asked) patches to fix the root cause of test failures
|
|
101
|
+
- Updating and creating test cases, fixtures, mocks, test data and configs
|
|
102
|
+
- Validating integrations (CI/CD, containers, runners, environments)
|
|
103
|
+
- Surfacing reliability and coverage gaps
|
|
104
|
+
|
|
105
|
+
When applying patches, follow repository style and AGENTS.md rules.
|
|
106
|
+
Avoid modifying unrelated code and avoid adding technical debt.
|
|
107
|
+
|
|
108
|
+
Common use cases include:
|
|
109
|
+
|
|
110
|
+
- Test execution automation
|
|
111
|
+
- Manual exploratory testing documentation
|
|
112
|
+
- Test case generation from requirements
|
|
113
|
+
- Assertions improvements and selector stabilization
|
|
114
|
+
- Test coverage analysis
|
|
115
|
+
- Defect reproduction and debugging
|
|
116
|
+
- Root cause attribution (test vs product defect)
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Handling files
|
|
121
|
+
|
|
122
|
+
### CRITICAL: File creation and modification rules
|
|
123
|
+
|
|
124
|
+
**NEVER output entire file contents in your response.** Always use tools to write files.
|
|
125
|
+
|
|
126
|
+
When creating or modifying files:
|
|
127
|
+
|
|
128
|
+
1. **Use incremental writes for new files**: Create files in logical sections using multiple tool calls:
|
|
129
|
+
- First call: Create file with initial structure (imports, class definition header)
|
|
130
|
+
- Subsequent calls: Add methods, functions, or sections one at a time using edit/append
|
|
131
|
+
- This prevents context overflow and ensures each part is properly written
|
|
132
|
+
|
|
133
|
+
2. **Use edit tools for modifications**: Use `filesystem_edit_file` for precise text replacement instead of rewriting entire files
|
|
134
|
+
|
|
135
|
+
3. **Never dump code in chat**: If you find yourself about to write a large code block in your response, STOP and use a file tool instead
|
|
136
|
+
|
|
137
|
+
Example - creating a test file correctly:
|
|
138
|
+
```
|
|
139
|
+
# Call 1: Create file with structure
|
|
140
|
+
filesystem_write_file("test_api.py", "import pytest\\nimport requests\\n\\n")
|
|
141
|
+
|
|
142
|
+
# Call 2: Append first test class/method
|
|
143
|
+
filesystem_append_file("test_api.py", "class TestAPI:\\n def test_health(self):\\n assert requests.get('/health').status_code == 200\\n")
|
|
144
|
+
|
|
145
|
+
# Call 3: Append second test method
|
|
146
|
+
filesystem_append_file("test_api.py", "\\n def test_auth(self):\\n assert requests.get('/protected').status_code == 401\\n")
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Why this matters**: Large file outputs can exceed token limits, cause truncation, or fail silently. Incremental writes are reliable and verifiable.
|
|
150
|
+
|
|
151
|
+
### Reading large files
|
|
152
|
+
|
|
153
|
+
When working with large files (logs, test reports, data files, source code):
|
|
154
|
+
|
|
155
|
+
- **Read in chunks**: Use offset and limit parameters to read files in manageable sections (e.g., 500-1000 lines at a time)
|
|
156
|
+
- **Start with structure**: First scan the file to understand its layout before diving into specific sections
|
|
157
|
+
- **Target relevant sections**: Once you identify the area of interest, read only that portion in detail
|
|
158
|
+
- **Avoid full loads**: Loading entire large files into context can cause models to return empty or incomplete responses due to context limitations
|
|
159
|
+
|
|
160
|
+
Example approach:
|
|
161
|
+
1. Read first 100 lines to understand file structure
|
|
162
|
+
2. Search/grep for relevant patterns to locate target sections
|
|
163
|
+
3. Read specific line ranges where issues or relevant code exist
|
|
164
|
+
|
|
165
|
+
### Writing and updating files
|
|
166
|
+
|
|
167
|
+
When modifying files, especially large ones:
|
|
168
|
+
|
|
169
|
+
- **Update in pieces**: Make targeted edits to specific sections, paragraphs, or functions rather than rewriting entire files
|
|
170
|
+
- **Use precise replacements**: Replace exact strings with sufficient context (3-5 lines before/after) to ensure unique matches
|
|
171
|
+
- **Batch related changes**: Group logically related edits together, but keep each edit focused and minimal
|
|
172
|
+
- **Preserve structure**: Maintain existing formatting, indentation, and file organization
|
|
173
|
+
- **Avoid full rewrites**: Never regenerate an entire file when only a portion needs changes
|
|
174
|
+
|
|
175
|
+
### Context limitations warning
|
|
176
|
+
|
|
177
|
+
**Important**: When context becomes too large (many files, long outputs, extensive history), some models may return empty or truncated responses. If you notice this:
|
|
178
|
+
|
|
179
|
+
- Summarize previous findings before continuing
|
|
180
|
+
- Focus on one file or task at a time
|
|
181
|
+
- Clear irrelevant context from consideration
|
|
182
|
+
- Break complex operations into smaller, sequential steps
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Sandbox and approvals
|
|
187
|
+
|
|
188
|
+
Sandboxing and approval rules are identical to coding agents, but framed around testing actions:
|
|
189
|
+
|
|
190
|
+
You may need escalation before:
|
|
191
|
+
|
|
192
|
+
- Creating or modifying files
|
|
193
|
+
- Installing testing dependencies
|
|
194
|
+
- Running network-dependent test suites
|
|
195
|
+
- Performing destructive cleanup actions
|
|
196
|
+
- Triggering CI pipelines or test runs that write outside workspace
|
|
197
|
+
|
|
198
|
+
If sandbox modes and approval rules are not specified, assume:
|
|
199
|
+
|
|
200
|
+
- Filesystem: `workspace-write`
|
|
201
|
+
- Network: ON
|
|
202
|
+
- Approval: `on-failure`
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Validating your work
|
|
207
|
+
|
|
208
|
+
Validation is core to your job.
|
|
209
|
+
|
|
210
|
+
- After fixing tests, rerun only the relevant subset first
|
|
211
|
+
- If stable, run broader suites to validate no regressions
|
|
212
|
+
- Avoid running full suites unnecessarily when in approval modes that require escalation
|
|
213
|
+
|
|
214
|
+
If there are no tests for the change you made, and the project has an established testing pattern, you may add one.
|
|
215
|
+
|
|
216
|
+
Avoid fixing unrelated tests unless the user requests it.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Presenting your work and final message
|
|
221
|
+
|
|
222
|
+
Your final message should feel like an update from a senior test engineer handing off state.
|
|
223
|
+
|
|
224
|
+
Good patterns include:
|
|
225
|
+
|
|
226
|
+
- What was tested
|
|
227
|
+
- What failed and why
|
|
228
|
+
- What was fixed
|
|
229
|
+
- Where files were changed
|
|
230
|
+
- How to validate locally
|
|
231
|
+
|
|
232
|
+
You should not dump full file contents unless the user asks. Reference files and paths directly.
|
|
233
|
+
|
|
234
|
+
If relevant, offer optional next steps such as:
|
|
235
|
+
|
|
236
|
+
- Running full regression
|
|
237
|
+
- Adding missing tests
|
|
238
|
+
- Improving coverage or performance
|
|
239
|
+
- Integrating into CI
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Answer formatting rules in CLI
|
|
244
|
+
|
|
245
|
+
Keep results scannable and technical:
|
|
246
|
+
|
|
247
|
+
- Use section headers only where they improve clarity
|
|
248
|
+
- Use short bullet lists (4–6 key bullets)
|
|
249
|
+
- Use backticks for code, commands, test names, file paths
|
|
250
|
+
- Reference files individually to keep them clickable (e.g. `tests/ui/login.spec.ts:44`)
|
|
251
|
+
- Avoid nested bullet lists or long paragraphs
|
|
252
|
+
|
|
253
|
+
Tone: pragmatic, precise, and focused on improving testing reliability and coverage.
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
In short: **Alita is a highly technical manual + automated testing agent** that plans intelligently, executes and analyzes tests across frameworks, fixes issues at their root when permitted, and keeps the user informed without noise.
|
|
258
|
+
"""
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent executor creation and management.
|
|
3
|
+
|
|
4
|
+
Creates LLM instances and agent executors with support for MCP tools.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Optional, Dict, Any, List, Tuple
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from .agent_loader import build_agent_data_structure
|
|
11
|
+
from alita_sdk.runtime.langchain.assistant import Assistant
|
|
12
|
+
|
|
13
|
+
console = Console()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def create_llm_instance(client, model: Optional[str], agent_def: Dict[str, Any],
|
|
17
|
+
temperature: Optional[float], max_tokens: Optional[int]):
|
|
18
|
+
"""Create LLM instance with appropriate configuration."""
|
|
19
|
+
llm_model = model or agent_def.get('model', 'gpt-4o')
|
|
20
|
+
llm_temperature = temperature if temperature is not None else agent_def.get('temperature', 0.7)
|
|
21
|
+
llm_max_tokens = max_tokens or agent_def.get('max_tokens', 2000)
|
|
22
|
+
|
|
23
|
+
try:
|
|
24
|
+
llm = client.get_llm(
|
|
25
|
+
model_name=llm_model,
|
|
26
|
+
model_config={
|
|
27
|
+
'temperature': llm_temperature,
|
|
28
|
+
'max_tokens': llm_max_tokens
|
|
29
|
+
}
|
|
30
|
+
)
|
|
31
|
+
return llm, llm_model, llm_temperature, llm_max_tokens
|
|
32
|
+
except Exception as e:
|
|
33
|
+
console.print(f"\n✗ [red]Failed to create LLM instance:[/red] {e}")
|
|
34
|
+
console.print("[yellow]Hint: Make sure OPENAI_API_KEY or other LLM credentials are set[/yellow]")
|
|
35
|
+
raise
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _create_assistant(client, agent_data: Dict[str, Any], llm, memory, tools: List) -> Assistant:
|
|
39
|
+
"""Create Assistant instance with given configuration.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
client: Alita client instance
|
|
43
|
+
agent_data: Agent configuration data
|
|
44
|
+
llm: LLM instance
|
|
45
|
+
memory: Memory/checkpoint instance
|
|
46
|
+
tools: List of tools to add to agent
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Assistant instance
|
|
50
|
+
"""
|
|
51
|
+
return Assistant(
|
|
52
|
+
alita=client,
|
|
53
|
+
data=agent_data,
|
|
54
|
+
client=llm,
|
|
55
|
+
chat_history=[],
|
|
56
|
+
app_type=agent_data.get('agent_type', 'react'),
|
|
57
|
+
tools=tools,
|
|
58
|
+
memory=memory,
|
|
59
|
+
store=None,
|
|
60
|
+
debug_mode=False,
|
|
61
|
+
mcp_tokens=None
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def create_agent_executor(client, agent_def: Dict[str, Any], toolkit_configs: List[Dict[str, Any]],
|
|
66
|
+
llm, llm_model: str, llm_temperature: float, llm_max_tokens: int, memory,
|
|
67
|
+
filesystem_tools: Optional[List] = None, mcp_tools: Optional[List] = None,
|
|
68
|
+
terminal_tools: Optional[List] = None, planning_tools: Optional[List] = None):
|
|
69
|
+
"""Create agent executor for local agents with tools (sync version).
|
|
70
|
+
|
|
71
|
+
Note: mcp_tools parameter is deprecated - use create_agent_executor_with_mcp for MCP support.
|
|
72
|
+
"""
|
|
73
|
+
agent_data = build_agent_data_structure(
|
|
74
|
+
agent_def=agent_def,
|
|
75
|
+
toolkit_configs=toolkit_configs,
|
|
76
|
+
llm_model=llm_model,
|
|
77
|
+
llm_temperature=llm_temperature,
|
|
78
|
+
llm_max_tokens=llm_max_tokens
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Combine all tools
|
|
82
|
+
additional_tools = []
|
|
83
|
+
if filesystem_tools:
|
|
84
|
+
additional_tools.extend(filesystem_tools)
|
|
85
|
+
if terminal_tools:
|
|
86
|
+
additional_tools.extend(terminal_tools)
|
|
87
|
+
if planning_tools:
|
|
88
|
+
additional_tools.extend(planning_tools)
|
|
89
|
+
if mcp_tools:
|
|
90
|
+
additional_tools.extend(mcp_tools)
|
|
91
|
+
|
|
92
|
+
assistant = _create_assistant(client, agent_data, llm, memory, additional_tools)
|
|
93
|
+
return assistant.runnable()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
async def create_agent_executor_with_mcp(
|
|
97
|
+
client,
|
|
98
|
+
agent_def: Dict[str, Any],
|
|
99
|
+
toolkit_configs: List[Dict[str, Any]],
|
|
100
|
+
llm,
|
|
101
|
+
llm_model: str,
|
|
102
|
+
llm_temperature: float,
|
|
103
|
+
llm_max_tokens: int,
|
|
104
|
+
memory,
|
|
105
|
+
filesystem_tools: Optional[List] = None,
|
|
106
|
+
terminal_tools: Optional[List] = None,
|
|
107
|
+
planning_tools: Optional[List] = None
|
|
108
|
+
) -> Tuple[Any, Optional[Any]]:
|
|
109
|
+
"""Create agent executor with MCP tools using persistent sessions.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Tuple of (agent_executor, mcp_session_manager) where session_manager must be kept alive
|
|
113
|
+
to maintain stateful MCP server state (e.g., Playwright browser sessions).
|
|
114
|
+
|
|
115
|
+
See: https://github.com/langchain-ai/langchain-mcp-adapters/issues/178
|
|
116
|
+
"""
|
|
117
|
+
from .mcp_loader import load_mcp_tools_async
|
|
118
|
+
|
|
119
|
+
# Separate MCP toolkit configs from regular configs
|
|
120
|
+
mcp_configs = [tc for tc in toolkit_configs if tc.get('toolkit_type') == 'mcp']
|
|
121
|
+
regular_configs = [tc for tc in toolkit_configs if tc.get('toolkit_type') != 'mcp']
|
|
122
|
+
|
|
123
|
+
# Load MCP tools with persistent sessions
|
|
124
|
+
mcp_session_manager = None
|
|
125
|
+
mcp_tools = []
|
|
126
|
+
if mcp_configs:
|
|
127
|
+
console.print("\n[cyan]Loading MCP tools with persistent sessions...[/cyan]")
|
|
128
|
+
mcp_session_manager, mcp_tools = await load_mcp_tools_async(mcp_configs)
|
|
129
|
+
if mcp_tools:
|
|
130
|
+
console.print(f"[green]✓ Loaded {len(mcp_tools)} MCP tools with persistent sessions[/green]\n")
|
|
131
|
+
|
|
132
|
+
# Build agent data structure
|
|
133
|
+
agent_data = build_agent_data_structure(
|
|
134
|
+
agent_def=agent_def,
|
|
135
|
+
toolkit_configs=regular_configs,
|
|
136
|
+
llm_model=llm_model,
|
|
137
|
+
llm_temperature=llm_temperature,
|
|
138
|
+
llm_max_tokens=llm_max_tokens
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Combine all tools
|
|
142
|
+
additional_tools = []
|
|
143
|
+
if filesystem_tools:
|
|
144
|
+
additional_tools.extend(filesystem_tools)
|
|
145
|
+
if terminal_tools:
|
|
146
|
+
additional_tools.extend(terminal_tools)
|
|
147
|
+
if planning_tools:
|
|
148
|
+
additional_tools.extend(planning_tools)
|
|
149
|
+
if mcp_tools:
|
|
150
|
+
additional_tools.extend(mcp_tools)
|
|
151
|
+
|
|
152
|
+
assistant = _create_assistant(client, agent_data, llm, memory, additional_tools)
|
|
153
|
+
|
|
154
|
+
# Return agent and session manager (must be kept alive for stateful MCP tools)
|
|
155
|
+
return assistant.runnable(), mcp_session_manager
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Agent loading and definition management.
|
|
3
|
+
|
|
4
|
+
Handles loading agent definitions from various file formats (YAML, JSON, Markdown).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import yaml
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Dict, Any
|
|
11
|
+
from pydantic import SecretStr
|
|
12
|
+
|
|
13
|
+
from .config import substitute_env_vars
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def load_agent_definition(file_path: str) -> Dict[str, Any]:
|
|
17
|
+
"""
|
|
18
|
+
Load agent definition from file.
|
|
19
|
+
|
|
20
|
+
Supports:
|
|
21
|
+
- YAML files (.yaml, .yml)
|
|
22
|
+
- JSON files (.json)
|
|
23
|
+
- Markdown files with YAML frontmatter (.md)
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
file_path: Path to agent definition file
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Dictionary with agent configuration
|
|
30
|
+
"""
|
|
31
|
+
path = Path(file_path)
|
|
32
|
+
|
|
33
|
+
if not path.exists():
|
|
34
|
+
raise FileNotFoundError(f"Agent definition not found: {file_path}")
|
|
35
|
+
|
|
36
|
+
content = path.read_text()
|
|
37
|
+
|
|
38
|
+
# Handle markdown with YAML frontmatter
|
|
39
|
+
if path.suffix == '.md':
|
|
40
|
+
if content.startswith('---'):
|
|
41
|
+
parts = content.split('---', 2)
|
|
42
|
+
if len(parts) >= 3:
|
|
43
|
+
frontmatter = yaml.safe_load(parts[1])
|
|
44
|
+
system_prompt = parts[2].strip()
|
|
45
|
+
|
|
46
|
+
# Apply environment variable substitution
|
|
47
|
+
system_prompt = substitute_env_vars(system_prompt)
|
|
48
|
+
|
|
49
|
+
return {
|
|
50
|
+
'name': frontmatter.get('name', path.stem),
|
|
51
|
+
'description': frontmatter.get('description', ''),
|
|
52
|
+
'system_prompt': system_prompt,
|
|
53
|
+
'model': frontmatter.get('model'),
|
|
54
|
+
'tools': frontmatter.get('tools', []),
|
|
55
|
+
'temperature': frontmatter.get('temperature'),
|
|
56
|
+
'max_tokens': frontmatter.get('max_tokens'),
|
|
57
|
+
'toolkit_configs': frontmatter.get('toolkit_configs', []),
|
|
58
|
+
'filesystem_tools_preset': frontmatter.get('filesystem_tools_preset'),
|
|
59
|
+
'filesystem_tools_include': frontmatter.get('filesystem_tools_include'),
|
|
60
|
+
'filesystem_tools_exclude': frontmatter.get('filesystem_tools_exclude'),
|
|
61
|
+
'mcps': frontmatter.get('mcps', [])
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Plain markdown - use content as system prompt
|
|
65
|
+
return {
|
|
66
|
+
'name': path.stem,
|
|
67
|
+
'system_prompt': substitute_env_vars(content),
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Handle YAML
|
|
71
|
+
if path.suffix in ['.yaml', '.yml']:
|
|
72
|
+
content = substitute_env_vars(content)
|
|
73
|
+
config = yaml.safe_load(content)
|
|
74
|
+
if 'system_prompt' in config:
|
|
75
|
+
config['system_prompt'] = substitute_env_vars(config['system_prompt'])
|
|
76
|
+
return config
|
|
77
|
+
|
|
78
|
+
# Handle JSON
|
|
79
|
+
if path.suffix == '.json':
|
|
80
|
+
content = substitute_env_vars(content)
|
|
81
|
+
config = json.loads(content)
|
|
82
|
+
if 'system_prompt' in config:
|
|
83
|
+
config['system_prompt'] = substitute_env_vars(config['system_prompt'])
|
|
84
|
+
return config
|
|
85
|
+
|
|
86
|
+
raise ValueError(f"Unsupported file format: {path.suffix}")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def unwrap_secrets(obj: Any) -> Any:
|
|
90
|
+
"""
|
|
91
|
+
Recursively unwrap pydantic SecretStr values into plain strings.
|
|
92
|
+
|
|
93
|
+
Handles nested dicts, lists, tuples, and sets while preserving structure.
|
|
94
|
+
"""
|
|
95
|
+
if isinstance(obj, SecretStr):
|
|
96
|
+
return obj.get_secret_value()
|
|
97
|
+
if isinstance(obj, dict):
|
|
98
|
+
return {k: unwrap_secrets(v) for k, v in obj.items()}
|
|
99
|
+
if isinstance(obj, list):
|
|
100
|
+
return [unwrap_secrets(v) for v in obj]
|
|
101
|
+
if isinstance(obj, tuple):
|
|
102
|
+
return tuple(unwrap_secrets(v) for v in obj)
|
|
103
|
+
if isinstance(obj, set):
|
|
104
|
+
return {unwrap_secrets(v) for v in obj}
|
|
105
|
+
return obj
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def build_agent_data_structure(agent_def: Dict[str, Any], toolkit_configs: list,
|
|
109
|
+
llm_model: str, llm_temperature: float, llm_max_tokens: int) -> Dict[str, Any]:
|
|
110
|
+
"""
|
|
111
|
+
Convert a local agent definition to the data structure expected by the Assistant class.
|
|
112
|
+
|
|
113
|
+
This utility function bridges between simple agent definition formats (e.g., from markdown files)
|
|
114
|
+
and the structured format that the Assistant class requires internally.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
agent_def: The agent definition loaded from a local file (markdown, YAML, or JSON)
|
|
118
|
+
toolkit_configs: List of toolkit configurations to be used by the agent
|
|
119
|
+
llm_model: The LLM model name (e.g., 'gpt-4o')
|
|
120
|
+
llm_temperature: Temperature setting for the model
|
|
121
|
+
llm_max_tokens: Maximum tokens for model responses
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
A dictionary in the format expected by the Assistant constructor with keys:
|
|
125
|
+
- instructions: System prompt for the agent
|
|
126
|
+
- tools: List of tool/toolkit configurations
|
|
127
|
+
- variables: Agent variables (empty for local agents)
|
|
128
|
+
- meta: Metadata including step_limit and internal_tools
|
|
129
|
+
- llm_settings: Complete LLM configuration
|
|
130
|
+
- agent_type: Type of agent (react, openai, etc.)
|
|
131
|
+
"""
|
|
132
|
+
# Import toolkit registry to validate configs
|
|
133
|
+
from alita_sdk.tools import AVAILABLE_TOOLS
|
|
134
|
+
|
|
135
|
+
# Build the tools list from agent definition and toolkit configs
|
|
136
|
+
tools = []
|
|
137
|
+
processed_toolkit_names = set()
|
|
138
|
+
|
|
139
|
+
# Validate and process toolkit configs through their Pydantic schemas
|
|
140
|
+
validated_toolkit_configs = []
|
|
141
|
+
for toolkit_config in toolkit_configs:
|
|
142
|
+
toolkit_type = toolkit_config.get('type')
|
|
143
|
+
if toolkit_type and toolkit_type in AVAILABLE_TOOLS:
|
|
144
|
+
try:
|
|
145
|
+
toolkit_info = AVAILABLE_TOOLS[toolkit_type]
|
|
146
|
+
if 'toolkit_class' in toolkit_info:
|
|
147
|
+
toolkit_class = toolkit_info['toolkit_class']
|
|
148
|
+
if hasattr(toolkit_class, 'toolkit_config_schema'):
|
|
149
|
+
schema = toolkit_class.toolkit_config_schema()
|
|
150
|
+
validated_config = schema(**toolkit_config)
|
|
151
|
+
# Use python mode so SecretStr remains as objects, then unwrap recursively
|
|
152
|
+
validated_dict = unwrap_secrets(validated_config.model_dump(mode="python"))
|
|
153
|
+
validated_dict['type'] = toolkit_config.get('type')
|
|
154
|
+
validated_dict['toolkit_name'] = toolkit_config.get('toolkit_name')
|
|
155
|
+
validated_toolkit_configs.append(validated_dict)
|
|
156
|
+
else:
|
|
157
|
+
validated_toolkit_configs.append(toolkit_config)
|
|
158
|
+
else:
|
|
159
|
+
validated_toolkit_configs.append(toolkit_config)
|
|
160
|
+
except Exception:
|
|
161
|
+
validated_toolkit_configs.append(toolkit_config)
|
|
162
|
+
else:
|
|
163
|
+
validated_toolkit_configs.append(toolkit_config)
|
|
164
|
+
|
|
165
|
+
# Add tools from agent definition
|
|
166
|
+
for tool_name in agent_def.get('tools', []):
|
|
167
|
+
toolkit_config = next((tk for tk in validated_toolkit_configs if tk.get('toolkit_name') == tool_name), None)
|
|
168
|
+
if toolkit_config:
|
|
169
|
+
tools.append({
|
|
170
|
+
'type': toolkit_config.get('type'),
|
|
171
|
+
'toolkit_name': toolkit_config.get('toolkit_name'),
|
|
172
|
+
'settings': toolkit_config,
|
|
173
|
+
'selected_tools': toolkit_config.get('selected_tools', [])
|
|
174
|
+
})
|
|
175
|
+
processed_toolkit_names.add(tool_name)
|
|
176
|
+
else:
|
|
177
|
+
tools.append({
|
|
178
|
+
'type': tool_name,
|
|
179
|
+
'name': tool_name
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
# Add toolkit_configs that weren't already referenced
|
|
183
|
+
for toolkit_config in validated_toolkit_configs:
|
|
184
|
+
toolkit_name = toolkit_config.get('toolkit_name')
|
|
185
|
+
if toolkit_name and toolkit_name not in processed_toolkit_names:
|
|
186
|
+
tools.append({
|
|
187
|
+
'type': toolkit_config.get('type'),
|
|
188
|
+
'toolkit_name': toolkit_name,
|
|
189
|
+
'settings': toolkit_config,
|
|
190
|
+
'selected_tools': toolkit_config.get('selected_tools', [])
|
|
191
|
+
})
|
|
192
|
+
return {
|
|
193
|
+
'instructions': agent_def.get('system_prompt', ''),
|
|
194
|
+
'tools': tools,
|
|
195
|
+
'variables': [],
|
|
196
|
+
'meta': {
|
|
197
|
+
'step_limit': agent_def.get('step_limit', 25),
|
|
198
|
+
'internal_tools': agent_def.get('internal_tools', [])
|
|
199
|
+
},
|
|
200
|
+
'llm_settings': {
|
|
201
|
+
'model_name': llm_model,
|
|
202
|
+
'max_tokens': llm_max_tokens,
|
|
203
|
+
'temperature': llm_temperature,
|
|
204
|
+
'integration_uid': None,
|
|
205
|
+
'indexer_config': {
|
|
206
|
+
'ai_model': 'langchain_openai.ChatOpenAI',
|
|
207
|
+
'ai_model_params': {
|
|
208
|
+
'model': llm_model,
|
|
209
|
+
'temperature': llm_temperature,
|
|
210
|
+
'max_tokens': llm_max_tokens
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
},
|
|
214
|
+
'agent_type': agent_def.get('agent_type', 'react')
|
|
215
|
+
}
|